import { RepositoryFactory } from '../database/repositories/index.js';
import { PerformanceMetric } from '../database/models/index.js';

interface PerformanceData {
  operation: string;
  executionTime: number;
  success: boolean;
  timestamp?: Date;
  metadata?: Record<string, any>;
}

interface PerformanceStats {
  totalOperations: number;
  averageTime: number;
  successRate: number;
  operationCounts: Record<string, number>;
  slowestOperations: Array<{
    operation: string;
    executionTime: number;
    timestamp: Date;
  }>;
}

/**
 * 性能监控管理器
 * 收集、存储和分析性能指标
 */
export class PerformanceMonitor {
  private static instance: PerformanceMonitor;
  private repositories?: RepositoryFactory;
  private metricsBuffer: PerformanceData[] = [];
  private bufferSize = 100;
  private flushInterval = 30000; // 30秒
  private flushTimer?: NodeJS.Timeout;

  constructor(repositories?: RepositoryFactory) {
    this.repositories = repositories;
    this.startAutoFlush();
  }

  /**
   * 获取单例实例
   */
  static getInstance(repositories?: RepositoryFactory): PerformanceMonitor {
    if (!PerformanceMonitor.instance) {
      PerformanceMonitor.instance = new PerformanceMonitor(repositories);
    }
    return PerformanceMonitor.instance;
  }

  /**
   * 记录性能指标
   */
  record(data: PerformanceData): void {
    const metric = {
      ...data,
      timestamp: data.timestamp || new Date(),
    };

    this.metricsBuffer.push(metric);

    // 输出实时监控日志
    this.logMetric(metric);

    // 检查缓冲区大小
    if (this.metricsBuffer.length >= this.bufferSize) {
      this.flushMetrics().catch(error => {
        console.error('❌ Failed to flush metrics:', error);
      });
    }
  }

  /**
   * 记录操作执行时间的装饰器
   */
  measureTime<T extends (...args: any[]) => any>(
    operation: string,
    fn: T,
    metadata?: Record<string, any>
  ): T {
    const monitor = this;
    
    return (async function(this: any, ...args: any[]) {
      const startTime = Date.now();
      let success = true;
      let result: any;
      
      try {
        result = await fn.apply(this, args);
        return result;
      } catch (error) {
        success = false;
        throw error;
      } finally {
        const executionTime = Date.now() - startTime;
        monitor.record({
          operation,
          executionTime,
          success,
          metadata: {
            ...metadata,
            args: args.length > 0 ? args.slice(0, 2) : undefined, // 只记录前两个参数
          },
        });
      }
    } as any) as T;
  }

  /**
   * 创建性能测量器
   */
  createMeasure(operation: string, metadata?: Record<string, any>) {
    const startTime = Date.now();
    
    return {
      end: (success: boolean = true, additionalMetadata?: Record<string, any>) => {
        const executionTime = Date.now() - startTime;
        this.record({
          operation,
          executionTime,
          success,
          metadata: {
            ...metadata,
            ...additionalMetadata,
          },
        });
      },
    };
  }

  /**
   * 批量刷新指标到数据库
   */
  async flushMetrics(): Promise<void> {
    if (this.metricsBuffer.length === 0 || !this.repositories) {
      return;
    }

    try {
      const metrics = this.metricsBuffer.splice(0); // 取出所有待刷新的指标
      
      // 转换为数据库格式
      const dbMetrics = metrics.map(metric => ({
        operation_type: metric.operation,
        execution_time_ms: metric.executionTime,
        cache_hit: metric.metadata?.cacheHit || false,
      }));

      // 批量写入数据库
      // 注意：这里需要创建 PerformanceMetric 实例而不是直接使用 bulkCreate
      for (const metric of dbMetrics) {
        try {
          await PerformanceMetric.create(metric);
        } catch (error) {
          console.warn('⚠️  Failed to save performance metric:', error);
        }
      }
      
      console.debug(`📊 Flushed ${dbMetrics.length} performance metrics to database`);
    } catch (error) {
      console.error('❌ Failed to flush performance metrics:', error);
      // 如果写入失败，可以考虑将指标重新放回缓冲区
    }
  }

  /**
   * 获取性能统计
   */
  async getStats(
    timeRange?: {
      from: Date;
      to: Date;
    },
    operationType?: string
  ): Promise<PerformanceStats> {
    if (!this.repositories) {
      return this.getLocalStats();
    }

    try {
      // 从数据库获取统计数据
      return await this.getDatabaseStats(timeRange, operationType);
    } catch (error) {
      console.error('❌ Failed to get database stats:', error);
      return this.getLocalStats();
    }
  }

  /**
   * 从数据库获取统计数据
   */
  private async getDatabaseStats(
    timeRange?: {
      from: Date;
      to: Date;
    },
    operationType?: string
  ): Promise<PerformanceStats> {
    if (!this.repositories) {
      throw new Error('Database repositories not available');
    }

    const repo = this.repositories.getComponentRepository();
    const connection = repo['connection']; // 访问数据库连接

    // 构建查询条件
    let whereClause = '1=1';
    const replacements: any[] = [];
    
    if (timeRange) {
      whereClause += ' AND timestamp BETWEEN ? AND ?';
      replacements.push(timeRange.from, timeRange.to);
    }
    
    if (operationType) {
      whereClause += ' AND operation_type = ?';
      replacements.push(operationType);
    }

    // 基础统计查询
    const basicStatsQuery = `
      SELECT 
        COUNT(*) as totalOperations,
        AVG(execution_time_ms) as averageTime,
        AVG(CASE WHEN cache_hit = 1 THEN 1 ELSE 0 END) as successRate,
        operation_type
      FROM performance_metrics 
      WHERE ${whereClause}
      GROUP BY operation_type
    `;

    // 最慢操作查询
    const slowestQuery = `
      SELECT operation_type as operation, execution_time_ms as executionTime, timestamp
      FROM performance_metrics 
      WHERE ${whereClause}
      ORDER BY execution_time_ms DESC
      LIMIT 10
    `;

    const [basicStats, slowestOps] = await Promise.all([
      connection.executeRawQuery(basicStatsQuery, replacements),
      connection.executeRawQuery(slowestQuery, replacements),
    ]);

    // 聚合结果
    const totalOps = basicStats.reduce((sum: number, stat: any) => sum + parseInt(stat.totalOperations), 0);
    const avgTime = basicStats.reduce((sum: number, stat: any) => sum + (parseFloat(stat.averageTime) * parseInt(stat.totalOperations)), 0) / totalOps || 0;
    const successRate = basicStats.reduce((sum: number, stat: any) => sum + (parseFloat(stat.successRate) * parseInt(stat.totalOperations)), 0) / totalOps || 0;
    
    const operationCounts: Record<string, number> = {};
    basicStats.forEach((stat: any) => {
      operationCounts[stat.operation_type] = parseInt(stat.totalOperations);
    });

    return {
      totalOperations: totalOps,
      averageTime: Math.round(avgTime * 100) / 100,
      successRate: Math.round(successRate * 100) / 100,
      operationCounts,
      slowestOperations: slowestOps.map((op: any) => ({
        operation: op.operation,
        executionTime: parseInt(op.executionTime),
        timestamp: new Date(op.timestamp),
      })),
    };
  }

  /**
   * 从本地缓冲区获取统计数据
   */
  private getLocalStats(): PerformanceStats {
    const metrics = this.metricsBuffer;
    
    if (metrics.length === 0) {
      return {
        totalOperations: 0,
        averageTime: 0,
        successRate: 0,
        operationCounts: {},
        slowestOperations: [],
      };
    }

    const totalOps = metrics.length;
    const avgTime = metrics.reduce((sum, m) => sum + m.executionTime, 0) / totalOps;
    const successRate = metrics.filter(m => m.success).length / totalOps;
    
    const operationCounts: Record<string, number> = {};
    metrics.forEach(m => {
      operationCounts[m.operation] = (operationCounts[m.operation] || 0) + 1;
    });

    const slowestOperations = metrics
      .sort((a, b) => b.executionTime - a.executionTime)
      .slice(0, 10)
      .map(m => ({
        operation: m.operation,
        executionTime: m.executionTime,
        timestamp: m.timestamp || new Date(),
      }));

    return {
      totalOperations: totalOps,
      averageTime: Math.round(avgTime * 100) / 100,
      successRate: Math.round(successRate * 100) / 100,
      operationCounts,
      slowestOperations,
    };
  }

  /**
   * 输出指标日志
   */
  private logMetric(metric: PerformanceData): void {
    const status = metric.success ? '✅' : '❌';
    const timeColor = metric.executionTime > 1000 ? '🐌' : metric.executionTime > 500 ? '⚠️' : '⚡';
    
    console.debug(`${status} ${timeColor} [${metric.operation}] ${metric.executionTime}ms`);
    
    // 如果执行时间过长，发出警告
    if (metric.executionTime > 2000) {
      console.warn(`🚨 Slow operation detected: ${metric.operation} took ${metric.executionTime}ms`);
    }
  }

  /**
   * 开始自动刷新
   */
  private startAutoFlush(): void {
    this.flushTimer = setInterval(() => {
      this.flushMetrics().catch(error => {
        console.error('❌ Auto flush failed:', error);
      });
    }, this.flushInterval);
  }

  /**
   * 生成性能报告
   */
  async generateReport(timeRange?: { from: Date; to: Date }): Promise<string> {
    try {
      const stats = await this.getStats(timeRange);
      
      return `
📊 性能监控报告
==================

📈 总体统计:
  - 总操作数: ${stats.totalOperations.toLocaleString()}
  - 平均耗时: ${stats.averageTime}ms
  - 成功率: ${(stats.successRate * 100).toFixed(1)}%

🔥 操作统计:
${Object.entries(stats.operationCounts)
  .sort((a, b) => b[1] - a[1])
  .map(([op, count]) => `  - ${op}: ${count.toLocaleString()}次`)
  .join('\n')}

🐌 最慢操作:
${stats.slowestOperations
  .map((op, i) => `  ${i + 1}. ${op.operation}: ${op.executionTime}ms (${op.timestamp.toISOString()})`)
  .join('\n')}

📅 报告时间: ${new Date().toISOString()}
      `.trim();
    } catch (error) {
      return `❌ 生成性能报告失败: ${error instanceof Error ? error.message : String(error)}`;
    }
  }

  /**
   * 清理资源
   */
  cleanup(): void {
    if (this.flushTimer) {
      clearInterval(this.flushTimer);
      this.flushTimer = undefined;
    }
    
    // 最后一次刷新
    this.flushMetrics().catch(console.error);
  }
}